package com.raidan.dclog.core.parser.text;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;

import com.raidan.dclog.core.Const;
import com.raidan.dclog.core.Utils;
import com.raidan.dclog.core.parser.ParseLineException;

/**
 * Main class for parsing Downloads.log and Uploads.log
 * 
 * @author raidan
 */
public class DownloadsTextParser extends AbstractTextParser {

	// private SimpleDateFormat timeFormatter;

	public DownloadsTextParser() {
		// this.timeFormatter = new SimpleDateFormat(this.getTimeFormat());
	}

	protected boolean isDownload() {
		return true;
	}

	//
	// @Override
	// protected void processLine(int linePos, String line, PreparedStatement
	// statement) throws SQLException,
	// ParseLineException {
	//
	// // 2009-01-17 23:25: C:\Program Files\PeLinkDC\Settings\files.xml.bz2
	// // Отдано vitek00 (), 756348 (756348), 0 Байт/s, 0:00:00
	//
	// int delimPos = line.indexOf(':');
	// if (delimPos < 0) {
	// throw new ParseLineException("Unable to propery parse line '" + line +
	// "' Not found : symbol.");
	//
	// }
	// delimPos = line.indexOf(':', delimPos + 1);
	// if (delimPos < 0) {
	// throw new ParseLineException("Unable to propery parse line '" + line +
	// "' Not found : symbol.");
	//
	// }
	//
	// // ---------------------------------
	// String datetime = line.substring(0, delimPos);
	//
	// // Избавляемся от возможного лишнего символа в начале файла UTF
	// if (linePos == 1) {
	// char ch = datetime.charAt(0);
	// if (ch < '0' || ch > '9') {
	// datetime = datetime.substring(1);
	// }
	// }
	//
	// char chars[] = line.toCharArray();
	// int lastDelimPos = Utils.getBackIndexOf(chars, ',', 0);
	//
	// // String lines[] = line.split(",");
	// String tmp = null;
	// String tempStr = null;
	//
	// // ---------------------------------
	// int speedDelimPos = Utils.getBackIndexOf(chars, ',', lastDelimPos);
	// tmp = line.substring(speedDelimPos + 1, lastDelimPos); // 0 Байт/s
	// double speed = Double.parseDouble(Utils.replaceAll(tmp.substring(0,
	// tmp.lastIndexOf(' ')), ",", "."));
	// String type = tmp.substring(tmp.lastIndexOf(' ') + 1);
	//
	// if (type.length() == 0) {
	// throw new ParseLineException("Unable to determine speed type: '" + type +
	// "'");
	// }
	//
	// String typeKey =
	// Character.toString(Character.toUpperCase(type.charAt(0)));
	//
	// if (bytesSpeedMark.contains(typeKey)) {
	// //
	// } else if (kbytesSpeedMark.contains(typeKey)) {
	// speed = speed * 1024;
	// } else if (mbytesSpeedMark.contains(typeKey)) {
	// speed = speed * 1024 * 1024;
	// } else if (gbytesSpeedMark.contains(typeKey)) {
	// speed = speed * 1024 * 1024 * 1024;
	// } else {
	// // Can't recognize speed? Bad.
	// throw new ParseLineException("Unable to determine speed type: '" + type +
	// "'");
	// }
	//
	// // ---------------------------------
	// int sizeDelimPos = Utils.getBackIndexOf(chars, ',', speedDelimPos);
	// tmp = line.substring(sizeDelimPos + 1, speedDelimPos); // 756348
	// // (756348)
	// tempStr = tmp.substring(tmp.lastIndexOf('(') + 1, tmp.lastIndexOf(')'));
	// long actualSize = tempStr.length() == 0 ? 0 : Long.parseLong(tempStr);
	//
	// // --------------------------------
	// // String username = matcher.group(++groupCount);
	// tmp = lines[lines.length - 2]; // common string :)
	//
	// // if (true) {
	// // int statementCount = 0;
	// // statement.setTimestamp(++statementCount, new
	// // Timestamp(System.currentTimeMillis()));
	// // statement.setString(++statementCount,
	// // "F:\\Download-torrent\\100.scene.DaniellaRush.by.Warlock-PT");
	// // statement.setString(++statementCount,
	// // "A.Feu.Et.A.Sexe.Sur.La.Riviera_DaniellaRush.avi");
	// // statement
	// // .setString(++statementCount,
	// //
	// "F:\\Download-torrent\\100.scene.DaniellaRush.by.Warlock-PT\\A.Feu.Et.A.Sexe.Sur.La.Riviera_DaniellaRush.avi");
	// //
	// // statement.setString(++statementCount, "ivan187");
	// // statement.setLong(++statementCount, 108544);
	// // statement.setInt(++statementCount, (int) 458658);
	// // statement.setString(++statementCount, this.isDownload() ?
	// // Const.LOADS_LOAD_TYPE_DOWNLOAD
	// // : Const.LOADS_LOAD_TYPE_UPLOAD);
	// //
	// // statement.addBatch();
	// // return;
	// // }
	//
	// // Matcher matcher = super.getLinePattern().matcher(line);
	// // if (!matcher.find(0)) {
	// // throw new ParseLineException("Unable to propery parse line '" + line
	// // + "' by pattern '"
	// // + super.getLinePattern().toString() + "'.");
	// // }
	// //
	// // int groupCount = 0;
	// // String datetime = matcher.group(++groupCount);
	// // String path = matcher.group(++groupCount);
	// //
	// // if (path.trim().length() != 0) {
	// //
	// // String fullPath = path;
	// // int pos = path.lastIndexOf("\\");
	// // String filename = path.substring(pos + 1);
	// // path = path.substring(0, pos);
	// //
	// // String username = matcher.group(++groupCount);
	// //
	// // String tempStr = matcher.group(++groupCount);
	// // // long totalSize = tempStr.length() == 0 ? 0 :
	// // // Long.parseLong(tempStr);
	// //
	// // tempStr = matcher.group(++groupCount);
	// // long actualSize = tempStr.length() == 0 ? 0 :
	// // Long.parseLong(tempStr);
	// //
	// // double speed =
	// // Double.parseDouble(Utils.replaceAll(matcher.group(++groupCount), ",",
	// // "."));
	// // String type = matcher.group(++groupCount);
	// //
	// // if (type.length() == 0) {
	// // throw new ParseLineException("Unable to determine speed type: '" +
	// // type + "'");
	// // }
	// //
	// // String typeKey =
	// // Character.toString(Character.toUpperCase(type.charAt(0)));
	// //
	// // if (bytesSpeedMark.contains(typeKey)) {
	// // //
	// // } else if (kbytesSpeedMark.contains(typeKey)) {
	// // speed = speed * 1024;
	// // } else if (mbytesSpeedMark.contains(typeKey)) {
	// // speed = speed * 1024 * 1024;
	// // } else if (gbytesSpeedMark.contains(typeKey)) {
	// // speed = speed * 1024 * 1024 * 1024;
	// // } else {
	// // // Can't recognize speed? Bad.
	// // throw new ParseLineException("Unable to determine speed type: '" +
	// // type + "'");
	// // }
	// //
	// // // String time = matcher.group(8);
	// //
	// // int statementCount = 0;
	// //
	// // // try {
	// // statement.setTimestamp(++statementCount, new
	// // Timestamp(System.currentTimeMillis()));
	// // // statement.setTimestamp(++statementCount, new
	// // // java.sql.Timestamp(super.getDateTimeFormatter().parse(
	// // // datetime).getTime())); // date
	// // // } catch (ParseException pe) {
	// // // throw new
	// // // ParseLineException("Unable to properly parse date for template '"
	// // // + super.getDateTimeFormatter().toPattern() + "' in line '" + line
	// // // + "': " + pe.getMessage());
	// // // }
	// // statement.setString(++statementCount, path);
	// // statement.setString(++statementCount, filename);
	// // statement.setString(++statementCount, fullPath);
	// //
	// // statement.setString(++statementCount, username);
	// // // statement.setLong(6, totalSize);
	// // statement.setLong(++statementCount, actualSize);
	// // statement.setInt(++statementCount, (int) speed);
	// // // try {
	// // // statement.setInt(9, (int) timeFormatter.parse(time).getTime() /
	// // // 1000);
	// // // } catch (ParseException pe) {
	// // // throw new
	// // // ParseLineException("Unable to properly parse time for template '"
	// // // + timeFormatter.toPattern()
	// // // + "' in line '" + line + "': " + pe.getMessage());
	// // // }
	// // statement.setString(++statementCount, this.isDownload() ?
	// // Const.LOADS_LOAD_TYPE_DOWNLOAD
	// // : Const.LOADS_LOAD_TYPE_UPLOAD);
	// //
	// // statement.addBatch();
	// //
	// // }
	//
	// }

	@Override
	protected void processLine(int linePos, String line, PreparedStatement statement) throws SQLException,
			ParseLineException {

		// 2009-01-17 23:25: C:\Program Files\PeLinkDC\Settings\files.xml.bz2
		// Отдано vitek00 (), 756348 (756348), 0 Байт/s, 0:00:00

		Matcher matcher = super.getLinePattern().matcher(line);
		if (!matcher.find(0)) {
			throw new ParseLineException("Unable to propery parse line '" + line + "' by pattern '"
					+ super.getLinePattern().toString() + "'.");
		}

		int groupCount = 0;
		String datetime = matcher.group(++groupCount);
		String path = matcher.group(++groupCount);

		if (path.trim().length() != 0) {

			String fullPath = path;
			int pos = path.lastIndexOf("\\");
			String filename = path.substring(pos + 1);
			path = path.substring(0, pos);

			String username = matcher.group(++groupCount);

			String tempStr = matcher.group(++groupCount);
			// long totalSize = tempStr.length() == 0 ? 0 :
			// Long.parseLong(tempStr);

			tempStr = matcher.group(++groupCount);
			long actualSize = tempStr.length() == 0 ? 0 : Long.parseLong(tempStr);

			double speed = Double.parseDouble(Utils.replaceAll(matcher.group(++groupCount), ",", "."));
			String type = matcher.group(++groupCount);

			if (type.length() == 0) {
				throw new ParseLineException("Unable to determine speed type: '" + type + "'");
			}

			String typeKey = Character.toString(Character.toUpperCase(type.charAt(0)));

			if (bytesSpeedMark.contains(typeKey)) {
				//
			} else if (kbytesSpeedMark.contains(typeKey)) {
				speed = speed * 1024;
			} else if (mbytesSpeedMark.contains(typeKey)) {
				speed = speed * 1024 * 1024;
			} else if (gbytesSpeedMark.contains(typeKey)) {
				speed = speed * 1024 * 1024 * 1024;
			} else {
				// Can't recognize speed? Bad.
				throw new ParseLineException("Unable to determine speed type: '" + type + "'");
			}

			// String time = matcher.group(8);

			int statementCount = 0;

			try {
				statement.setTimestamp(++statementCount, new java.sql.Timestamp(super.getDateTimeFormatter().parse(
						datetime).getTime())); // date
			} catch (ParseException pe) {
				throw new ParseLineException("Unable to properly parse date for template '"
						+ super.getDateTimeFormatter().toPattern() + "' in line '" + line + "': " + pe.getMessage());
			}
			statement.setString(++statementCount, path);
			statement.setString(++statementCount, filename);
			statement.setString(++statementCount, fullPath);

			statement.setString(++statementCount, username);
			// statement.setLong(6, totalSize);
			statement.setLong(++statementCount, actualSize);
			statement.setInt(++statementCount, (int) speed);
			// try {
			// statement.setInt(9, (int) timeFormatter.parse(time).getTime() /
			// 1000);
			// } catch (ParseException pe) {
			// throw new
			// ParseLineException("Unable to properly parse time for template '"
			// + timeFormatter.toPattern()
			// + "' in line '" + line + "': " + pe.getMessage());
			// }
			statement.setString(++statementCount, this.isDownload() ? Const.LOADS_LOAD_TYPE_DOWNLOAD
					: Const.LOADS_LOAD_TYPE_UPLOAD);

			statement.addBatch();

		}

	}

	@Override
	protected String getSQLInsert() {
		return "insert into loads (changed, path, filename, full_path, username, actual_size, speed, load_type) "
				+ "values (?, ?, ?, ?, ?, ?, ?, ?)";
		// return
		// "insert into loads (changed, path, filename, full_path, username, total_size, actual_size, speed, loadtime, load_type) "
		// + "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
	}

	@Override
	public String getName() {
		return "Downloads logs";
	}

	@Override
	protected String getFileName() {
		return "Downloads.log";
	}

	@Override
	protected String getPattern() {
		return ".*(\\d\\d\\d\\d-\\d\\d-\\d\\d \\d\\d:\\d\\d): (.*) (?:(?:Скачано от)|(?:downloaded from)) "
				+ "([^ ]+) \\(\\), (-?\\d+) \\((\\d*)\\), ([\\d,]+) ([^,]+), ([\\d:]*)";
	}

	// Determine speed of download
	private static final Set<String> bytesSpeedMark = new HashSet<String>();
	private static final Set<String> kbytesSpeedMark = new HashSet<String>();
	private static final Set<String> mbytesSpeedMark = new HashSet<String>();
	private static final Set<String> gbytesSpeedMark = new HashSet<String>();

	// private static final String downloadedWords[] = new String[] {
	// " downloaded from ", " Скачано от " };
	// private static final String uploadedWords[] = new String[] {
	// " uploaded to ", " Отдано " };

	static {
		bytesSpeedMark.add("Б");
		bytesSpeedMark.add("B");

		kbytesSpeedMark.add("К");
		kbytesSpeedMark.add("K");

		mbytesSpeedMark.add("М");
		mbytesSpeedMark.add("M");

		gbytesSpeedMark.add("Г");
		gbytesSpeedMark.add("G");
	}

}
